<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>应用管理</title>
  <link rel="stylesheet" href="../assets/styles.css" />
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body class="body-bg">
  <header class="header">
    <div class="title datav-title">河北省高速公路联网收费省级密钥资源池管理系统</div>
  </header>
  <div class="layout">
    <aside class="sidebar">
      <!-- <div class="logo">密钥资源池</div> -->
      <div class="logo">应用管理</div>
      <nav class="menu">
        <a href="../index.html">首页</a>
        <a class="active" href="app.html">应用管理</a>
        <a href="crypto.html">加密设备状态</a>
        <a href="security.html">安全设备状态</a>
        <a href="network.html">部省密钥网络状态</a>
        <a href="jobs.html">定时任务</a>
      </nav>
      <div class="tree">
        <div class="tree-node">
          <div class="tree-header">报表管理<span class="chevron"></span></div>
          <div class="tree-children">
            <a class="tree-link" href="reports.html?tab=app" data-tab="app">服务调用统计</a>
            <a class="tree-link" href="reports.html?tab=crypto" data-tab="crypto">加密设备运行监测</a>
            <a class="tree-link" href="reports.html?tab=security" data-tab="security">安全设备运行监测</a>
            <a class="tree-link" href="reports.html?tab=network" data-tab="network">部省密钥网络运行报表</a>
          </div>
        </div>
      </div>
    </aside>
    <div class="content">
      <main class="container">
    <section class="grid cols-2" style="margin-top:16px;">
      <div class="card datav">
        <h3>调用次数 TOP10（近7天）</h3>
        <div class="chart-box">
          <canvas id="chartTop10Stacked"></canvas>
        </div>
      </div>
      <div class="card datav">
        <h3>成功率统计（近7天）</h3>
        <div class="chart-box" style="height:320px; padding:8px 12px;"><canvas id="chartSuccess"></canvas></div>
      </div>
      <div class="card datav">
         <h3>各模块调用趋势（近7天）</h3>
         <div class="chart-box"><canvas id="chartTrend"></canvas></div>
       </div>
      <div class="card datav">
        <h3>调用方统计（近7天）</h3>
        <div class="chart-box" style="height:320px;"><canvas id="chartBars"></canvas></div>
      </div>
    </section>
    <section class="card datav" style="margin-top:16px;">
      <h3>各模块调用统计（近7天）</h3>
      <div class="chart-box" style="height:320px;">
        <canvas id="chartModuleVendor"></canvas>
      </div>
    </section>

    <section class="card datav">
      <h3>调用记录</h3>
      <!-- <div class="filters">
        <div class="field"><label>接口名称</label><input class="input" placeholder="例如：/api/signature/verify"/></div>
        <div class="field"><label>调用时间</label>
          <select class="select" id="timeRange">
            <option>今日</option>
            <option>近7天</option>
          </select>
          <input class="input" type="date" />
          <input class="input" type="date" />
        </div>
        <div class="field"><label>调用状态</label>
          <select class="select" id="status">
            <option value="">全部</option>
            <option>成功</option>
            <option>失败</option>
          </select>
        </div>
        <div class="field"><label>调用方</label><input class="input" placeholder="IP 或名称"/></div>
        <button class="button">查询</button>
        <button class="button secondary">重置</button>
      </div> -->
      <h3 style="margin-top:12px;">调用记录列表</h3>
      <table class="table" id="records">
        <thead>
          <tr>
            <th>接口名称</th><th>调用时间</th><th>返回结果</th><th>耗时(ms)</th>
          </tr>
        </thead>
        <tbody id="recordsBody"></tbody>
      </table>
      <!-- <div class="hint">默认每页 10 条，可分页与列自定义显示。</div> -->
    </section>
    <!-- <section class="card datav" style="margin-top:16px;">
      <h3>数据管理区</h3>
      <div>当前留存调用总数（7天）：<strong>12,430</strong></div>
      <button class="button warning" id="cleanupBtn" style="margin-top:10px;">手动触发清理（二次确认）</button>
    </section> -->
      </main>
    </div>
  </div>

  <script>
    // 调用次数 TOP10（近7天）：横向单柱图（显示总次数）
    
    const labelsTop10 = [
        'CPU卡一发获取业务单据号',
        'CPU卡一发更新密钥',
        'CPU卡一发更新0015文件',
        'CPU卡一发上送发行结果',
        'CPU卡二发获取业务单据号',
        'CPU用户卡0016文件更新',
        'CPU用户卡0015文件更新',
        'CPU卡发行结果上送',
        'CPU卡修改车辆信息申请',
        'CPU卡修改有效期申请'
    ];

    // 原本是分模块堆叠，这里改为生成总次数数据
    const moduleCounts = Array.from({ length: 5 }, () =>
      Array.from({ length: 10 }, () => Math.floor(40 + Math.random() * 160))
    );
    const totalsTop10 = Array.from({ length: 10 }, (_, i) =>
      moduleCounts.reduce((sum, arr) => sum + arr[i], 0)
    );
    new Chart(document.getElementById('chartTop10Stacked'), {
      type: 'bar',
      data: {
        labels: labelsTop10,
        datasets: [
          { label: '总调用次数', backgroundColor: '#3b82f6', data: totalsTop10 }
        ]
      },
      options: {
        indexAxis: 'y',
        responsive: true,
        maintainAspectRatio: false,
        scales: {
          x: { stacked: false, ticks: { color: '#cbd5e1' }, grid: { color: 'rgba(148,163,184,0.15)' } },
          y: { stacked: false, ticks: { color: '#cbd5e1' }, grid: { display: false } }
        },
        plugins: { legend: { labels: { color: '#e5e7eb' } }, tooltip: { mode: 'nearest', intersect: false } }
      }
    });

    // 成功率环形图（双环：内圈成功，外圈失败；分模块占比）
     const moduleDefs = [
       { name: 'PSAM卡', color: '#3b82f6', fail: 'rgba(59,130,246,0.35)' },
       { name: 'CPU卡',  color: '#8b5cf6', fail: 'rgba(139,92,246,0.35)' },
       { name: 'ETC卡',  color: '#10b981', fail: 'rgba(16,185,129,0.35)' },
       { name: 'OBU卡',  color: '#f59e0b', fail: 'rgba(245,158,11,0.35)' },
       { name: 'CPC卡',  color: '#ef4444', fail: 'rgba(239,68,68,0.35)' }
     ];
     const labelsSuccess = moduleDefs.map(m => m.name);
     // 示例数据：后续可替换为真实统计数据
     const successByModule = [420, 360, 380, 300, 290];
     const failByModule    = [35,  42,  28,  25,  20];
     new Chart(document.getElementById('chartSuccess'), {
       type: 'doughnut',
       data: {
         labels: labelsSuccess,
         datasets: [
           {
             label: '成功',
             data: successByModule,
             backgroundColor: moduleDefs.map(m => m.color),
             hoverOffset: 6,
             offset: 2,
             borderWidth: 0
           },
           {
             label: '失败',
             data: failByModule,
             backgroundColor: moduleDefs.map(m => m.fail),
             hoverOffset: 6,
             offset: 2,
             borderWidth: 0
           }
         ]
       },
        options: {
          radius: '88%',
          cutout: '60%',
          responsive: true,
          maintainAspectRatio: false,
          layout: { padding: { top: 8, right: 8, bottom: 8, left: 8 } },
          elements: { arc: { borderWidth: 0 } },
          plugins: {
            legend: {
              position: 'top',
              align: 'start',
              labels: {
                color: '#e5e7eb',
                padding: 12,
                boxWidth: 12,
                boxHeight: 12,
                usePointStyle: true,
                pointStyle: 'circle'
              }
            },
            tooltip: {
              callbacks: {
                label: (ctx) => {
                  const module = ctx.label;
                  const series = ctx.dataset.label;
                  const val = ctx.parsed;
                  const total = ctx.dataset.data.reduce((a, b) => a + b, 0);
                  const pct = total ? ((val / total) * 100).toFixed(1) : 0;
                  return `${series} · ${module}: ${val}（${pct}%）`;
                }
              }
            }
          }
        }
      });

      //（已移除）图表下方静态比例展示

    // 各模块调用趋势（近7天，多折线）
     const trendLabels = Array.from({length:7}, (_,i)=>`T-${7-i}`);
     const trendDatasets = (typeof moduleDefs !== 'undefined' ? moduleDefs : [
       { name: 'PSAM卡', color: '#3b82f6' },
       { name: 'CPU卡',  color: '#8b5cf6' },
       { name: 'ETC卡',  color: '#10b981' },
       { name: 'OBU卡',  color: '#f59e0b' },
       { name: 'CPC卡',  color: '#ef4444' }
     ]).map((m, idx) => ({
       label: m.name,
       borderColor: m.color,
       backgroundColor: 'transparent',
       tension: .3,
       data: Array.from({length:7}, () => 900 + Math.floor(Math.random()*200) + idx*30)
     }));
     new Chart(document.getElementById('chartTrend'), {
       type: 'line',
       data: { labels: trendLabels, datasets: trendDatasets },
       options: {
         plugins: { legend: { labels: { color: '#e5e7eb' } } },
         scales: {
           x: { ticks: { color: '#cbd5e1' }, grid: { color: 'rgba(148,163,184,0.12)' } },
           y: { ticks: { color: '#cbd5e1' }, grid: { color: 'rgba(148,163,184,0.12)' } }
         }
       }
     });

    // 调用方统计（分组柱状：成功/失败/总次数）
    (function initCallerStats(){
      const callers = ['调用方A','调用方B','调用方C','调用方D','调用方E'];
      const success = [320,280,260,240,220];
      const fail    = [20,30,40,25,35];
      const total   = callers.map((_,i) => success[i] + fail[i]);
      new Chart(document.getElementById('chartBars'), {
        type: 'bar',
        data: {
          labels: callers,
          datasets: [
            { label: '成功次数', data: success, backgroundColor: '#10b981' },
            { label: '失败次数', data: fail, backgroundColor: '#ef4444' },
            { label: '总次数',   data: total, backgroundColor: '#f59e0b' }
          ]
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          scales: {
            x: { stacked: false, ticks: { color: '#cbd5e1' }, grid: { color: 'rgba(148,163,184,0.12)' } },
            y: { stacked: false, ticks: { color: '#cbd5e1' }, grid: { color: 'rgba(148,163,184,0.12)' } }
          },
          plugins: { legend: { labels: { color: '#e5e7eb' } }, tooltip: { mode: 'index', intersect: false } }
        }
      });
    })();
    // 各模块调用统计（分发行方分组柱状图）
    (function initModuleVendor(){
      const modules = ['PSAM卡','CPU卡','ETC卡','OBU卡','CPC卡'];
      const datasets = [
        { label: '发行方1调用量', backgroundColor: '#3b82f6', data: [320,280,260,240,210] },
        { label: '发行方2调用量', backgroundColor: '#10b981', data: [260,230,220,210,190] },
        { label: '发行方3调用量', backgroundColor: '#f59e0b', data: [180,170,160,150,140] }
      ];
      const ctx = document.getElementById('chartModuleVendor');
      if (!ctx) return;
      new Chart(ctx, {
        type: 'bar',
        data: { labels: modules, datasets },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          scales: {
            x: { stacked: false, ticks: { color: '#cbd5e1' }, grid: { color: 'rgba(148,163,184,0.12)' } },
            y: { stacked: false, ticks: { color: '#cbd5e1' }, grid: { color: 'rgba(148,163,184,0.12)' } }
          },
          plugins: { legend: { labels: { color: '#e5e7eb' } }, tooltip: { mode: 'index', intersect: false } },
        }
      });
    })();

    // 调用记录列表：渲染 10 条示例数据
    (function initRecords(){
      const tbody = document.getElementById('recordsBody');
      if (!tbody) return;
      const apis = ['CPU卡一发获取业务单据号', 'CPU卡一发更新密钥', 'CPU卡一发更新0015文件', 'CPU卡一发上送发行结果', 'CPU卡二发获取业务单据号', 'CPU用户卡0016文件更新', 'CPU用户卡0015文件更新', 'CPU卡发行结果上送', 'CPU卡修改车辆信息申请', 'CPU卡修改有效期申请'];
      const now = new Date();
      const pad2 = n => String(n).padStart(2,'0');
      const fmt = dt => `${dt.getFullYear()}-${pad2(dt.getMonth()+1)}-${pad2(dt.getDate())} ${pad2(dt.getHours())}:${pad2(dt.getMinutes())}:${pad2(dt.getSeconds())}`;
      const rows = Array.from({length:10}, (_, i) => {
        const api = apis[i % apis.length];
        const dt = new Date(now.getTime() - (i * 60000));
        const ok = Math.random() > 0.2; // 80% 成功
        const result = ok ? '成功' : '失败';
        const duration = 30 + Math.floor(Math.random()*90);
        return `<tr><td>${api}</td><td>${fmt(dt)}</td><td>${result}</td><td>${duration}</td></tr>`;
      });
      tbody.innerHTML = rows.join('');
    })();
  </script>
  <script>
    const th = document.querySelector('.tree-header');
    if (th) th.addEventListener('click', () => th.parentElement.classList.toggle('expanded'));
    // 绑定筛选与清理事件
    const queryBtn = document.querySelector('.filters .button:not(.secondary)');
    const resetBtn = document.querySelector('.filters .button.secondary');
    const cleanupBtn = document.getElementById('cleanupBtn');
    if (queryBtn) {
      queryBtn.addEventListener('click', () => {
        console.log('[查询] 执行筛选请求');
        alert('已按筛选条件查询（示例行为）');
      });
    }
    if (resetBtn) {
      resetBtn.addEventListener('click', () => {
        document.querySelectorAll('.filters input').forEach(i => i.value = '');
        const s = document.getElementById('status'); if (s) s.value='';
        const t = document.getElementById('timeRange'); if (t) t.value='今日';
        console.log('[重置] 已清空筛选条件');
      });
    }
    if (cleanupBtn) {
      cleanupBtn.addEventListener('click', () => {
        if (confirm('确认执行清理操作？该操作不可撤销。')) {
          alert('已提交清理任务（示例行为）');
        }
      });
    }
  </script>
      <!-- 已移除（数据管理区已置于 main 容器内） -->
</body>
</html>